#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QFile>
#include <QDateTime>
#include <QTextStream>
#include <QSettings>
#include <QApplication>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    
    // 初始化文件系统模型
    model1 = new QFileSystemModel;
    model1->setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
    ui->treeView1->setModel(model1);
    
    model2 = new QFileSystemModel;
    model2->setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
    ui->treeView2->setModel(model2);
    
    // 初始化文件系统监视器
    watcher = new QFileSystemWatcher(this);
    connect(watcher, &QFileSystemWatcher::directoryChanged, this, &MainWindow::onDirectoryChanged);
    
    // 读取配置文件中的目录设置
    readConfig();
    
    // 如果配置文件中没有目录设置，则使用当前目录
    if (currentDir1.isEmpty()) {
        currentDir1 = QDir::currentPath();
    }
    if (currentDir2.isEmpty()) {
        currentDir2 = QDir::currentPath();
    }
    
    model1->setRootPath(currentDir1);
    ui->treeView1->setRootIndex(model1->index(currentDir1));
    ui->lineEdit1->setText(currentDir1);
    
    model2->setRootPath(currentDir2);
    ui->treeView2->setRootIndex(model2->index(currentDir2));
    ui->lineEdit2->setText(currentDir2);
    
    // 隐藏不需要的列
    for (int i = 1; i < model1->columnCount(); i++) {
        ui->treeView1->hideColumn(i);
        ui->treeView2->hideColumn(i);
    }
    
    // 设置目录监视
    setupDirectoryWatcher();
    
    updateStatus("就绪");
}

MainWindow::~MainWindow()
{
    // 在程序退出前保存配置
    writeConfig();
    
    delete ui;
    delete model1;
    delete model2;
    delete watcher;
}

void MainWindow::on_toolButton1_clicked()
{
    QString dir = QFileDialog::getExistingDirectory(this, "选择左侧目录", currentDir1);
    if (!dir.isEmpty()) {
        currentDir1 = dir;
        ui->lineEdit1->setText(currentDir1);
        ui->treeView1->setRootIndex(model1->index(currentDir1));
        writeConfig(); // 保存更新后的目录
        updateDirectoryWatch(); // 更新目录监视
    }
}

void MainWindow::on_toolButton2_clicked()
{
    QString dir = QFileDialog::getExistingDirectory(this, "选择右侧目录", currentDir2);
    if (!dir.isEmpty()) {
        currentDir2 = dir;
        ui->lineEdit2->setText(currentDir2);
        ui->treeView2->setRootIndex(model2->index(currentDir2));
        writeConfig(); // 保存更新后的目录
        updateDirectoryWatch(); // 更新目录监视
    }
}

// 处理目录变化信号
void MainWindow::onDirectoryChanged(const QString &path)
{
    // 刷新文件系统模型 - 使用正确的方法
    QModelIndex rootIndex1 = ui->treeView1->rootIndex();
    QModelIndex rootIndex2 = ui->treeView2->rootIndex();
    
    // 重新设置根路径来刷新模型
    model1->setRootPath(currentDir1);
    model2->setRootPath(currentDir2);
    
    // 恢复原来的根索引
    ui->treeView1->setRootIndex(rootIndex1);
    ui->treeView2->setRootIndex(rootIndex2);
    
    updateStatus(QString("目录已更新: %1").arg(path));
}

// 设置目录监视
void MainWindow::setupDirectoryWatcher()
{
    // 监视两个目录
    if (!currentDir1.isEmpty()) {
        if (!watcher->addPath(currentDir1)) {
            updateStatus(QString("无法监视目录: %1").arg(currentDir1));
        }
    }
    
    if (!currentDir2.isEmpty()) {
        if (!watcher->addPath(currentDir2)) {
            updateStatus(QString("无法监视目录: %1").arg(currentDir2));
        }
    }
}

// 更新目录监视
void MainWindow::updateDirectoryWatch()
{
    // 移除所有当前监视的路径
    QStringList paths = watcher->directories();
    watcher->removePaths(paths);
    
    // 添加新的监视路径
    setupDirectoryWatcher();
}

void MainWindow::on_treeView1_clicked(const QModelIndex &index)
{
    QString fileName = model1->fileName(index);
    QString filePath1 = model1->filePath(index);
    
    // 检查是否为文件（修复部分）
    if (model1->fileInfo(index).isFile()) {
        // 构建另一个目录中的同名文件路径
        QString filePath2 = currentDir2 + "/" + fileName;
        
        updateStatus("比较文件: " + fileName);
        // 在比较前设置提示信息
        ui->textEdit->setText("正在比较...");
        // 立即更新UI，确保用户能看到提示信息
        QApplication::processEvents();
        
        QString result = compareFiles(filePath1, filePath2);
        ui->textEdit->setText(result);
    }
}

void MainWindow::on_treeView2_clicked(const QModelIndex &index)
{
    QString fileName = model2->fileName(index);
    QString filePath2 = model2->filePath(index);
    
    // 检查是否为文件（修复部分）
    if (model2->fileInfo(index).isFile()) {
        // 构建另一个目录中的同名文件路径
        QString filePath1 = currentDir1 + "/" + fileName;
        
        updateStatus("比较文件: " + fileName);
        // 在比较前设置提示信息
        ui->textEdit->setText("正在比较...");
        // 立即更新UI，确保用户能看到提示信息
        QApplication::processEvents();
        
        QString result = compareFiles(filePath1, filePath2);
        ui->textEdit->setText(result);
    }
}

QString MainWindow::compareFiles(const QString &file1, const QString &file2)
{
    QTextStream out;
    QString result;
    
    // 以二进制模式打开文件
    QFile f1(file1);
    QFile f2(file2);
    
    if (!f1.open(QIODevice::ReadOnly)) {
        return "无法打开左侧文件: " + file1;
    }
    
    if (!f2.open(QIODevice::ReadOnly)) {
        f1.close();
        return "无法打开右侧文件: " + file2;
    }
    
    // 获取文件大小
    qint64 size1 = f1.size();
    qint64 size2 = f2.size();
    
    result += QString("左侧文件: %1\n").arg(file1);
    result += QString("右侧文件: %1\n").arg(file2);
    result += QString("左侧文件大小: %1 字节\n").arg(size1);
    result += QString("右侧文件大小: %1 字节\n").arg(size2);
    
    if (size1 != size2) {
        result += "文件大小不同!\n";
    }
    
    // 比较文件内容（以较小的文件大小为准）
    const qint64 compareSize = qMin(size1, size2);
    bool filesIdentical = true;
    qint64 firstDiffPos = 0;
    
    // 使用128MB缓冲区
    const qint64 bufferSize = 128 * 1024 * 1024; // 128MB
    
    // 创建缓冲区
    QByteArray buffer1, buffer2;
    buffer1.resize(bufferSize);
    buffer2.resize(bufferSize);
    
    qint64 bytesRead1, bytesRead2;
    qint64 pos = 0;
    
    // 使用指针而不是数组下标进行比较
    while (pos < compareSize) {
        qint64 currentReadSize = qMin(bufferSize, compareSize - pos);
        
        bytesRead1 = f1.read(buffer1.data(), currentReadSize);
        bytesRead2 = f2.read(buffer2.data(), currentReadSize);
        
        if (bytesRead1 != currentReadSize || bytesRead2 != currentReadSize) {
            result += "读取文件时出错!\n";
            f1.close();
            f2.close();
            return result;
        }
        
        // 使用指针进行字节比较
        char* ptr1 = buffer1.data();
        char* ptr2 = buffer2.data();
        char* end = ptr1 + currentReadSize;
        
        // 在缓冲区中查找第一个不同的字节
        while (ptr1 < end) {
            if (*ptr1 != *ptr2) {
                firstDiffPos = pos + (ptr1 - buffer1.data());
                filesIdentical = false;
                result += QString("文件在第%1字节(0索引)开始不同\n").arg(firstDiffPos);
                result += QString("左侧文件的字节: 0x%1\n").arg(static_cast<unsigned char>(*ptr1), 2, 16, QChar('0'));
                result += QString("右侧文件的字节: 0x%1\n").arg(static_cast<unsigned char>(*ptr2), 2, 16, QChar('0'));
                break;
            }
            ++ptr1;
            ++ptr2;
        }
        
        // 如果找到不同的字节，跳出外层循环
        if (!filesIdentical) {
            break;
        }
        
        pos += currentReadSize;
    }
    
    if (filesIdentical && size1 == size2) {
        result += "文件完全相同!\n";
    } else if (filesIdentical && size1 != size2) {
        result += QString("文件内容在前%1字节相同，但大小不同!\n").arg(compareSize);
    }
    
    // 添加比较时间
    result += QString("比较时间: %1\n").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
    
    f1.close();
    f2.close();
    return result;
}

void MainWindow::updateStatus(const QString &message)
{
    ui->statusBar->showMessage(message);
}

// 读取配置文件
void MainWindow::readConfig()
{
    // 创建QSettings对象，使用INI格式
    QSettings settings("config.ini", QSettings::IniFormat);
    
    // 读取目录设置
    currentDir1 = settings.value("Directories/LeftDirectory").toString();
    currentDir2 = settings.value("Directories/RightDirectory").toString();
}

// 写入配置文件
void MainWindow::writeConfig()
{
    // 创建QSettings对象，使用INI格式
    QSettings settings("config.ini", QSettings::IniFormat);
    
    // 写入目录设置
    settings.setValue("Directories/LeftDirectory", currentDir1);
    settings.setValue("Directories/RightDirectory", currentDir2);
    
    // 确保立即写入文件
    settings.sync();
}